Function: diff-context->unified
diff-context->unified is an interactive and byte-compiled function
defined in diff-mode.el.gz.
Signature
(diff-context->unified START END &optional TO-CONTEXT)
Documentation
Convert context diffs to unified diffs.
START and END are either taken from the region
(when it is highlighted) or else cover the whole buffer.
With a prefix argument, convert unified format to context format.
Probably introduced at or before Emacs version 22.1.
Key Bindings
Source Code
;; Defined in /usr/src/emacs/lisp/vc/diff-mode.el.gz
(defun diff-context->unified (start end &optional to-context)
"Convert context diffs to unified diffs.
START and END are either taken from the region
\(when it is highlighted) or else cover the whole buffer.
With a prefix argument, convert unified format to context format."
(interactive (if (use-region-p)
(list (region-beginning) (region-end) current-prefix-arg)
(list (point-min) (point-max) current-prefix-arg)))
(if to-context
(diff-unified->context start end)
(unless (markerp end) (setq end (copy-marker end t)))
(let ( ;;(diff-inhibit-after-change t)
(inhibit-read-only t))
(save-excursion
(goto-char start)
(while (and (re-search-forward "^\\(\\(\\*\\*\\*\\) .+\n\\(---\\) .+\\|\\*\\{15\\}.*\n\\*\\*\\* \\([0-9]+\\),\\(-?[0-9]+\\) \\*\\*\\*\\*\\)\\(?: \\(.*\\)\\|$\\)" nil t)
(< (point) end))
(combine-after-change-calls
(if (match-beginning 2)
;; we matched a file header
(progn
;; use reverse order to make sure the indices are kept valid
(replace-match "+++" t t nil 3)
(replace-match "---" t t nil 2))
;; we matched a hunk header
(let ((line1s (match-string 4))
(line1e (match-string 5))
(pt1 (match-beginning 0))
;; Variables to use the special undo function.
(old-undo buffer-undo-list)
(old-end (marker-position end))
;; We currently throw away the comment that can follow
;; the hunk header. FIXME: Preserve it instead!
(reversible (not (match-end 6))))
(replace-match "")
(unless (re-search-forward
diff-context-mid-hunk-header-re nil t)
(error "Can't find matching `--- n1,n2 ----' line"))
(let ((line2s (match-string 1))
(line2e (match-string 2))
(pt2 (progn
(delete-region (progn (beginning-of-line) (point))
(progn (forward-line 1) (point)))
(point-marker))))
(goto-char pt1)
(forward-line 1)
(while (< (point) pt2)
(pcase (char-after)
(?! (delete-char 2) (insert "-") (forward-line 1))
(?- (forward-char 1) (delete-char 1) (forward-line 1))
(?\s ;merge with the other half of the chunk
(let* ((endline2
(save-excursion
(goto-char pt2) (forward-line 1) (point))))
(pcase (char-after pt2)
((or ?! ?+)
(insert "+"
(prog1
(buffer-substring (+ pt2 2) endline2)
(delete-region pt2 endline2))))
(?\s
(unless (= (- endline2 pt2)
(- (line-beginning-position 2) (point)))
;; If the two lines we're merging don't have the
;; same length (can happen with "diff -b"), then
;; diff-unified->context will not properly undo
;; this operation.
(setq reversible nil))
(delete-region pt2 endline2)
(delete-char 1)
(forward-line 1))
(?\\ (forward-line 1))
(_ (setq reversible nil)
(delete-char 1) (forward-line 1)))))
(_ (setq reversible nil) (forward-line 1))))
(while (looking-at "[+! ] ")
(if (/= (char-after) ?!) (forward-char 1)
(delete-char 1) (insert "+"))
(delete-char 1) (forward-line 1))
(save-excursion
(goto-char pt1)
(insert "@@ -" line1s ","
(number-to-string (- (string-to-number line1e)
(string-to-number line1s)
-1))
" +" line2s ","
(number-to-string (- (string-to-number line2e)
(string-to-number line2s)
-1)) " @@"))
(set-marker pt2 nil)
;; The whole procedure succeeded, let's replace the myriad
;; of undo elements with just a single special one.
(unless (or (not reversible) (eq buffer-undo-list t))
(setq buffer-undo-list
(cons (list 'apply (- old-end end) pt1 (point)
'diff-unified->context pt1 (point))
old-undo)))
)))))))))